package com.edu.whty.common.tools;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.*;
import java.util.Enumeration;


public class HttpClient {

	private static Logger logger = LoggerFactory.getLogger(HttpClient.class);

	private static final String $line_feed = System.getProperty("line.separator");
	
	/**
	 * post方式提交请求
	 * 
	 * @param strURL
	 *            请求地址
	 * @param requestStr
	 *            参数值
	 * @return 服务器返回
	 * @throws Exception
	 */
	public static String doPostMethod(String strURL, String requestStr, String charset) throws Exception {
		StringBuffer sbReturn = new StringBuffer("");
		URL url = null;
		HttpURLConnection httpConnection = null;
		InputStream in = null;
		OutputStream out = null;
		BufferedReader br = null;
		//int timeout = Integer.parseInt(PaymentConfig.getPaymentConfig("http.timeout"));
		int timeout = 30000;
		try {
			url = new URL(strURL);
			httpConnection = (HttpURLConnection) url.openConnection();

			httpConnection.setRequestMethod("POST");
			//httpConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
			httpConnection.setRequestProperty("Content-Type","application/json");
			httpConnection.setRequestProperty("Cache-Control", "no-cache");
			httpConnection.setRequestProperty("Content-Length", String.valueOf(requestStr.length()));
			httpConnection.setRequestProperty("Cache-Control", "no-cache");
			httpConnection.setRequestProperty("accept", "*/*");

			httpConnection.setDoInput(true);
			httpConnection.setDoOutput(true);
			httpConnection.setConnectTimeout(timeout);
			httpConnection.setReadTimeout(timeout);
			
			httpConnection.setRequestProperty("x-forwarded-for", getIpAddr(strURL)); 
			out = httpConnection.getOutputStream();
			OutputStreamWriter osw = new OutputStreamWriter(out, charset);
			osw.write(requestStr);
			osw.flush();
			osw.close();

			in = httpConnection.getInputStream();
			br = new BufferedReader(new InputStreamReader(in, charset));
			String strRead = "";
			while ((strRead = br.readLine()) != null) {
				sbReturn.append(strRead);
				sbReturn.append($line_feed);
			}
			logger.info("Http return respone -->"+sbReturn.toString());
		} catch (Exception ex) {
			logger.info(strURL + "  get error message:   " + ex.getMessage());
			//ExceptionHander.throwPaymentException(ErrorCode.ERROR_REQUEST_PAYPLATFORM_FAILED);
		} finally {
			try {
				if (out != null)
					out.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (in != null)
					in.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (br != null)
					br.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (httpConnection != null)
					httpConnection.disconnect();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
		}
		return sbReturn.toString();
	}
	
	/**
	 * get方式提交请求
	 * 
	 * @param strURL
	 *            请求地址
	 * @param strURL
	 *            参数值
	 * @return 服务器返回
	 */
	public static String doGetMethod(String strURL) {
		HttpURLConnection httpConnection = null;
		StringBuffer sbReturn = new StringBuffer("");
		InputStream in = null;
		BufferedReader reader = null;
        try {
            URL address_url = new URL(strURL);
            httpConnection = (HttpURLConnection) address_url.openConnection();
			httpConnection.setRequestProperty("x-forwarded-for", getIpAddr(strURL)); 

            //设置访问超时时间及读取网页流的超时时间,毫秒值
            System.setProperty("sun.net.client.defaultConnectTimeout","30000");
            System.setProperty("sun.net.client.defaultReadTimeout", "30000");
            //得到访问页面的返回值
            int response_code = httpConnection.getResponseCode();
            if (response_code == HttpURLConnection.HTTP_OK) {
                in = httpConnection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
                String line = null;
                while ((line = reader.readLine()) != null) {
    				sbReturn.append(line);
    				sbReturn.append($line_feed);
                }
                logger.info("Http return response -->"+sbReturn.toString());
            }
        } catch (Exception ex) {
			logger.info(strURL + "  can't curl   " + ex.getMessage());
		} finally {
			try {
				if (in != null)
					in.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (reader != null)
					reader.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (httpConnection != null)
					httpConnection.disconnect();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
		}
		return sbReturn.toString();
    }
	
	
	
	/**
	 * post方式提交请求
	 * 
	 * @param strURL
	 *            请求地址
	 * @param requestStr
	 *            参数值
	 * @return 服务器返回
	 */
	public static String doJSONPostMethod(String strURL, String requestStr) throws Exception{
		StringBuffer sbReturn = new StringBuffer("");
		URL url = null;
		HttpURLConnection httpConnection = null;
		InputStream in = null;
		OutputStream out = null;
		BufferedReader br = null;
		//int timeout = Integer.parseInt(PaymentConfig.getPaymentConfig("http.timeout"));
		int timeout = 80000;
		try {
			url = new URL(strURL);
			httpConnection = (HttpURLConnection) url.openConnection();

			httpConnection.setRequestMethod("POST");
			httpConnection.setRequestProperty("Content-Type","application/json");
			httpConnection.setRequestProperty("Cache-Control", "no-cache");
			httpConnection.setRequestProperty("Content-Length", String.valueOf(requestStr.length()));
			httpConnection.setRequestProperty("Cache-Control", "no-cache");
			httpConnection.setRequestProperty("accept", "*/*");
			if(StringUtils.isNotBlank(getIpAddr(strURL))) {
				httpConnection.setRequestProperty("x-forwarded-for", getIpAddr(strURL));
			}

			httpConnection.setDoInput(true);
			httpConnection.setDoOutput(true);
			httpConnection.setConnectTimeout(timeout);
			httpConnection.setReadTimeout(timeout);

			out = httpConnection.getOutputStream();
			OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
			osw.write(requestStr);
			osw.flush();
			osw.close();

			in = httpConnection.getInputStream();
			br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			String strRead = "";
			while ((strRead = br.readLine()) != null) {
				sbReturn.append(strRead);
				sbReturn.append($line_feed);
			}
		} catch (Exception ex) {
			logger.info(strURL + "  can't curl   " + ex.getMessage());
			ex.printStackTrace();
		} finally {
			try {
				if (out != null)
					out.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (in != null)
					in.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (br != null)
					br.close();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
			try {
				if (httpConnection != null)
					httpConnection.disconnect();
			} catch (Exception fx) {
				fx.printStackTrace();
			}
		}
		String respString = sbReturn.toString();
		if(!strURL.contains("site_domain")){
			//logger.info("Http return requestUrl -->"+strURL);
			//logger.info("Http return response -->"+respString);
		}
		return respString;
	}
	
	/**
     * post方式提交请求
     * 
     * @param strURL
     *            请求地址
     * @param requestStr
     *            参数值
     * @return 服务器返回
     */
    public static String doJSONPostMethod(String strURL, String requestStr, int timeOut) throws Exception{
        StringBuffer sbReturn = new StringBuffer("");
        URL url = null;
        HttpURLConnection httpConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader br = null;
        //int timeout = Integer.parseInt(PaymentConfig.getPaymentConfig("http.timeout"));
        try {
            url = new URL(strURL);
            httpConnection = (HttpURLConnection) url.openConnection();

            httpConnection.setRequestMethod("POST");
            httpConnection.setRequestProperty("Content-Type","application/json");
            httpConnection.setRequestProperty("Cache-Control", "no-cache");
            httpConnection.setRequestProperty("Content-Length", String.valueOf(requestStr.length()));
            httpConnection.setRequestProperty("Cache-Control", "no-cache");
            httpConnection.setRequestProperty("accept", "*/*");
			httpConnection.setRequestProperty("x-forwarded-for", getIpAddr(strURL)); 

            httpConnection.setDoInput(true);
            httpConnection.setDoOutput(true);
            httpConnection.setConnectTimeout(timeOut);
            httpConnection.setReadTimeout(timeOut);

            out = httpConnection.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
            osw.write(requestStr);
            osw.flush();
            osw.close();

            in = httpConnection.getInputStream();
            br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String strRead = "";
            while ((strRead = br.readLine()) != null) {
                sbReturn.append(strRead);
                sbReturn.append($line_feed);
            }
        } catch (Exception ex) {
            logger.error(strURL + "  can't curl   " + ex.getMessage(), ex);
        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (Exception fx) {
                fx.printStackTrace();
            }
            try {
                if (in != null)
                    in.close();
            } catch (Exception fx) {
                fx.printStackTrace();
            }
            try {
                if (br != null)
                    br.close();
            } catch (Exception fx) {
                fx.printStackTrace();
            }
            try {
                if (httpConnection != null)
                    httpConnection.disconnect();
            } catch (Exception fx) {
                fx.printStackTrace();
            }
        }
        String respString = sbReturn.toString();
        logger.info("Http return response -->"+respString);
        return respString;
    }
    
	/**
	 * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
	 *
	 * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
	 * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
	 *
	 * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
	 *
	 * 用户真实IP为： 192.168.1.110
	 *
	 * @param request
	 * @return
	 */
	
	public static String getIpAdrress() {
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		String ip = null;

		if(requestAttributes==null) {
			//logger.info("requestAttributes为null");
		}
		
		if (null != requestAttributes) {
			HttpServletRequest request = requestAttributes.getRequest();
			logger.info("return x-forwarded-for -->"+request.getHeader("x-forwarded-for"));
			logger.info("return Proxy-Client-IP -->"+request.getHeader("Proxy-Client-IP"));
			logger.info("return WL-Proxy-Client-IP -->"+ request.getHeader("WL-Proxy-Client-IP"));
			logger.info("return HTTP_CLIENT_IP -->"+request.getHeader("HTTP_CLIENT_IP"));
			logger.info("return X-Real-IP -->"+request.getHeader("X-Real-IP"));
			logger.info("return X-Forwarded-For -->"+request.getHeader("X-Forwarded-For"));

			// X-Forwarded-For：Squid 服务代理
			String ipAddresses = request.getHeader("x-forwarded-for");
			String unknown = "unknown";
			if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
				// Proxy-Client-IP：apache 服务代理
				ipAddresses = request.getHeader("Proxy-Client-IP");
			}

			if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
				// WL-Proxy-Client-IP：weblogic 服务代理
				ipAddresses = request.getHeader("WL-Proxy-Client-IP");
			}

			if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
				// HTTP_CLIENT_IP：有些代理服务器
				ipAddresses = request.getHeader("HTTP_CLIENT_IP");
			}

			if (ipAddresses == null || ipAddresses.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
				// X-Real-IP：nginx服务代理
				ipAddresses = request.getHeader("X-Real-IP");
			}

			// 有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
			if (ipAddresses != null && ipAddresses.length() != 0) {
				ip = ipAddresses.split(",")[0];
			}

			// 还是不能获取到，最后再通过request.getRemoteAddr();获取
			if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ipAddresses)) {
				ip = request.getRemoteAddr();
			}
		}

		//logger.info("用户真实ip -->"+ip);
		return ip;
	}
		 
		
	
	
	/**
	 * 获取Linux下的IP地址
	 *
	 * @return IP地址
	 * @throws SocketException
	 */
	public static String getLinuxLocalIp() {
		String ip = "";
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				String name = intf.getName();
				if (!name.contains("docker") && !name.contains("lo")) {
					for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
						InetAddress inetAddress = enumIpAddr.nextElement();
						if (!inetAddress.isLoopbackAddress()) {
							String ipaddress = inetAddress.getHostAddress().toString();
							if (!ipaddress.contains("::") && !ipaddress.contains("0:0:")
									&& !ipaddress.contains("fe80")) {
								ip = ipaddress;
							}
						}
					}
				}
			}
		} catch (SocketException ex) {
			ex.printStackTrace();
		}
		logger.info("linux服务器 ip-->"+ip);
		return ip;
	}
    
	
	public static  String getIpAddr(String url) {
		
		if(url.contains("/smsService/sms/sendSms")||url.contains("/smsService/email/sendEmail")) {
			return  getLinuxLocalIp();
		}
		return  getIpAdrress();
	}

    /**
     * 验证url地址访问状态
     * @param urlAddr
     * @return
     * @throws Exception
     */
    public static Integer validateUrl(String urlAddr)throws Exception{
    	try{//
			URL url = new URL(urlAddr);
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			int statusCode = connection.getResponseCode();
			return statusCode;
    	}catch(Exception e){
			return 500;
		}
	}
}
